﻿
/* ==============================================================================
*
*   Copyright (c) 2010, Pierre Favier
*   All rights reserved.
*
*   NTasking is free software: you can redistribute it and/or modify it
*   under the terms of the GNU General Public License as published by the
*   Free Software Foundation.
*
*   Redistribution and use in source and binary forms, with or without
*   modification, are permitted provided that the following conditions
*   are met:
*
*   -   Redistributions of source code must retain the above copyright notice,
*       this list of conditions and the following disclaimer.
*
*   -   Redistributions in binary form must reproduce the above
*       copyright notice, this list of conditions and the following
*       disclaimer in the documentation and/or other materials
*       provided with the distribution.
*
*   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
*   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
*   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
*   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
*   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
*   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
*   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
*   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
*   ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
*   TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
*   THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
*   SUCH DAMAGE.
*
* ============================================================================== */

using System;
using System.Collections.Generic;
using NUnit.Framework;
using Rhino.Mocks;
using Rhino.Mocks.Constraints;

namespace NTasking.ValidationTests.Other.Capacities
{

    [TestFixture]
    public class Task : ValidationTest
    {
                
        internal class StraightAccept0 : ValidationTestTask
        {

            [Entry]
            internal Action NotUsed { get; private set; }

            [Entry]
            internal Action Put { get; private set; }
            [Entry]
            internal Func<bool> Get { get; private set; }
            [Entry]
            internal ActionFamily<double> FPut { get; private set; }
            [Entry]
            internal FuncFamily<double, bool> FGet { get; private set; }


            internal StraightAccept0(IValidationTestResult result)
                : base(result)
            {
            }


            protected override void Body()
            {

                Accept(Put, () => { }, null);
                Accept(Get, () => true, null);
                Accept(FPut, (i) => { }, null);
                Accept(FGet, (i) => true, null);
                Accept(FPut[0.0], (double i) => { }, null);
                Accept(FGet[0.0], (double i) => true, null);
                    
            }
            protected override void Exception(Exception ex)
            {
                Result.TestFailed();
                base.Exception(ex);
            }

        }
        
                
        internal class SelectiveAccept0 : ValidationTestTask
        {

            [Entry]
            internal Action NotUsed { get; private set; }

            [Entry]
            internal Action Put { get; private set; }
            [Entry]
            internal Func<bool> Get { get; private set; }
            [Entry]
            internal ActionFamily<double> FPut { get; private set; }
            [Entry]
            internal FuncFamily<double, bool> FGet { get; private set; }


            internal SelectiveAccept0(IValidationTestResult result)
                : base(result)
            {
            }


            protected override void Body()
            {

                while (true)
                {

                    Select(s => s.
                        When(() => true).
                            Accept(Put, () => { }).
                    Or.
                        When(() => true).
                            Accept(Get, () => true).
                    Or.
                        When(() => true).
                            Accept(FPut, (i) => { }).
                    Or.
                        When(() => true).
                            Accept(FGet, (i) => true).
                    Or.
                        When((double i) => true).
                            Accept(FPut, (i) => { }).
                    Or.
                        When((double i) => true).
                            Accept(FGet, (i) => true).
                    Or.
                        When(() => true).
                            Accept(FPut[0.0], (double i) => { }).
                    Or.
                        When(() => true).
                            Accept(FGet[0.0], (double i) => true).
                    Or.
                        Terminate
                    );

                }
                    
            }
            protected override void Exception(Exception ex)
            {
                Result.TestFailed();
                base.Exception(ex);
            }

        }
        
                
        internal class StraightAccept1 : ValidationTestTask
        {

            [Entry]
            internal Action NotUsed { get; private set; }

            [Entry]
            internal Action<int> Put { get; private set; }
            [Entry]
            internal Func<int, bool> Get { get; private set; }
            [Entry]
            internal ActionFamily<double, int> FPut { get; private set; }
            [Entry]
            internal FuncFamily<double, int, bool> FGet { get; private set; }


            internal StraightAccept1(IValidationTestResult result)
                : base(result)
            {
            }


            protected override void Body()
            {

                Accept(Put, (p1) => { }, null);
                Accept(Get, (p1) => true, null);
                Accept(FPut, (i, p1) => { }, null);
                Accept(FGet, (i, p1) => true, null);
                Accept(FPut[0.0], (double i, int p1) => { }, null);
                Accept(FGet[0.0], (double i, int p1) => true, null);
                    
            }
            protected override void Exception(Exception ex)
            {
                Result.TestFailed();
                base.Exception(ex);
            }

        }
        
                
        internal class SelectiveAccept1 : ValidationTestTask
        {

            [Entry]
            internal Action NotUsed { get; private set; }

            [Entry]
            internal Action<int> Put { get; private set; }
            [Entry]
            internal Func<int, bool> Get { get; private set; }
            [Entry]
            internal ActionFamily<double, int> FPut { get; private set; }
            [Entry]
            internal FuncFamily<double, int, bool> FGet { get; private set; }


            internal SelectiveAccept1(IValidationTestResult result)
                : base(result)
            {
            }


            protected override void Body()
            {

                while (true)
                {

                    Select(s => s.
                        When(() => true).
                            Accept(Put, (p1) => { }).
                    Or.
                        When(() => true).
                            Accept(Get, (p1) => true).
                    Or.
                        When(() => true).
                            Accept(FPut, (i, p1) => { }).
                    Or.
                        When(() => true).
                            Accept(FGet, (i, p1) => true).
                    Or.
                        When((double i) => true).
                            Accept(FPut, (i, p1) => { }).
                    Or.
                        When((double i) => true).
                            Accept(FGet, (i, p1) => true).
                    Or.
                        When(() => true).
                            Accept(FPut[0.0], (double i, int p1) => { }).
                    Or.
                        When(() => true).
                            Accept(FGet[0.0], (double i, int p1) => true).
                    Or.
                        Terminate
                    );

                }
                    
            }
            protected override void Exception(Exception ex)
            {
                Result.TestFailed();
                base.Exception(ex);
            }

        }
        
                
        internal class StraightAccept2 : ValidationTestTask
        {

            [Entry]
            internal Action NotUsed { get; private set; }

            [Entry]
            internal Action<int, int> Put { get; private set; }
            [Entry]
            internal Func<int, int, bool> Get { get; private set; }
            [Entry]
            internal ActionFamily<double, int, int> FPut { get; private set; }
            [Entry]
            internal FuncFamily<double, int, int, bool> FGet { get; private set; }


            internal StraightAccept2(IValidationTestResult result)
                : base(result)
            {
            }


            protected override void Body()
            {

                Accept(Put, (p1, p2) => { }, null);
                Accept(Get, (p1, p2) => true, null);
                Accept(FPut, (i, p1, p2) => { }, null);
                Accept(FGet, (i, p1, p2) => true, null);
                Accept(FPut[0.0], (double i, int p1, int p2) => { }, null);
                Accept(FGet[0.0], (double i, int p1, int p2) => true, null);
                    
            }
            protected override void Exception(Exception ex)
            {
                Result.TestFailed();
                base.Exception(ex);
            }

        }
        
                
        internal class SelectiveAccept2 : ValidationTestTask
        {

            [Entry]
            internal Action NotUsed { get; private set; }

            [Entry]
            internal Action<int, int> Put { get; private set; }
            [Entry]
            internal Func<int, int, bool> Get { get; private set; }
            [Entry]
            internal ActionFamily<double, int, int> FPut { get; private set; }
            [Entry]
            internal FuncFamily<double, int, int, bool> FGet { get; private set; }


            internal SelectiveAccept2(IValidationTestResult result)
                : base(result)
            {
            }


            protected override void Body()
            {

                while (true)
                {

                    Select(s => s.
                        When(() => true).
                            Accept(Put, (p1, p2) => { }).
                    Or.
                        When(() => true).
                            Accept(Get, (p1, p2) => true).
                    Or.
                        When(() => true).
                            Accept(FPut, (i, p1, p2) => { }).
                    Or.
                        When(() => true).
                            Accept(FGet, (i, p1, p2) => true).
                    Or.
                        When((double i) => true).
                            Accept(FPut, (i, p1, p2) => { }).
                    Or.
                        When((double i) => true).
                            Accept(FGet, (i, p1, p2) => true).
                    Or.
                        When(() => true).
                            Accept(FPut[0.0], (double i, int p1, int p2) => { }).
                    Or.
                        When(() => true).
                            Accept(FGet[0.0], (double i, int p1, int p2) => true).
                    Or.
                        Terminate
                    );

                }
                    
            }
            protected override void Exception(Exception ex)
            {
                Result.TestFailed();
                base.Exception(ex);
            }

        }
        
                
        internal class StraightAccept3 : ValidationTestTask
        {

            [Entry]
            internal Action NotUsed { get; private set; }

            [Entry]
            internal Action<int, int, int> Put { get; private set; }
            [Entry]
            internal Func<int, int, int, bool> Get { get; private set; }
            [Entry]
            internal ActionFamily<double, int, int, int> FPut { get; private set; }
            [Entry]
            internal FuncFamily<double, int, int, int, bool> FGet { get; private set; }


            internal StraightAccept3(IValidationTestResult result)
                : base(result)
            {
            }


            protected override void Body()
            {

                Accept(Put, (p1, p2, p3) => { }, null);
                Accept(Get, (p1, p2, p3) => true, null);
                Accept(FPut, (i, p1, p2, p3) => { }, null);
                Accept(FGet, (i, p1, p2, p3) => true, null);
                Accept(FPut[0.0], (double i, int p1, int p2, int p3) => { }, null);
                Accept(FGet[0.0], (double i, int p1, int p2, int p3) => true, null);
                    
            }
            protected override void Exception(Exception ex)
            {
                Result.TestFailed();
                base.Exception(ex);
            }

        }
        
                
        internal class SelectiveAccept3 : ValidationTestTask
        {

            [Entry]
            internal Action NotUsed { get; private set; }

            [Entry]
            internal Action<int, int, int> Put { get; private set; }
            [Entry]
            internal Func<int, int, int, bool> Get { get; private set; }
            [Entry]
            internal ActionFamily<double, int, int, int> FPut { get; private set; }
            [Entry]
            internal FuncFamily<double, int, int, int, bool> FGet { get; private set; }


            internal SelectiveAccept3(IValidationTestResult result)
                : base(result)
            {
            }


            protected override void Body()
            {

                while (true)
                {

                    Select(s => s.
                        When(() => true).
                            Accept(Put, (p1, p2, p3) => { }).
                    Or.
                        When(() => true).
                            Accept(Get, (p1, p2, p3) => true).
                    Or.
                        When(() => true).
                            Accept(FPut, (i, p1, p2, p3) => { }).
                    Or.
                        When(() => true).
                            Accept(FGet, (i, p1, p2, p3) => true).
                    Or.
                        When((double i) => true).
                            Accept(FPut, (i, p1, p2, p3) => { }).
                    Or.
                        When((double i) => true).
                            Accept(FGet, (i, p1, p2, p3) => true).
                    Or.
                        When(() => true).
                            Accept(FPut[0.0], (double i, int p1, int p2, int p3) => { }).
                    Or.
                        When(() => true).
                            Accept(FGet[0.0], (double i, int p1, int p2, int p3) => true).
                    Or.
                        Terminate
                    );

                }
                    
            }
            protected override void Exception(Exception ex)
            {
                Result.TestFailed();
                base.Exception(ex);
            }

        }
        
                
        internal class StraightAccept4 : ValidationTestTask
        {

            [Entry]
            internal Action NotUsed { get; private set; }

            [Entry]
            internal Action<int, int, int, int> Put { get; private set; }
            [Entry]
            internal Func<int, int, int, int, bool> Get { get; private set; }
            [Entry]
            internal ActionFamily<double, int, int, int, int> FPut { get; private set; }
            [Entry]
            internal FuncFamily<double, int, int, int, int, bool> FGet { get; private set; }


            internal StraightAccept4(IValidationTestResult result)
                : base(result)
            {
            }


            protected override void Body()
            {

                Accept(Put, (p1, p2, p3, p4) => { }, null);
                Accept(Get, (p1, p2, p3, p4) => true, null);
                Accept(FPut, (i, p1, p2, p3, p4) => { }, null);
                Accept(FGet, (i, p1, p2, p3, p4) => true, null);
                Accept(FPut[0.0], (double i, int p1, int p2, int p3, int p4) => { }, null);
                Accept(FGet[0.0], (double i, int p1, int p2, int p3, int p4) => true, null);
                    
            }
            protected override void Exception(Exception ex)
            {
                Result.TestFailed();
                base.Exception(ex);
            }

        }
        
                
        internal class SelectiveAccept4 : ValidationTestTask
        {

            [Entry]
            internal Action NotUsed { get; private set; }

            [Entry]
            internal Action<int, int, int, int> Put { get; private set; }
            [Entry]
            internal Func<int, int, int, int, bool> Get { get; private set; }
            [Entry]
            internal ActionFamily<double, int, int, int, int> FPut { get; private set; }
            [Entry]
            internal FuncFamily<double, int, int, int, int, bool> FGet { get; private set; }


            internal SelectiveAccept4(IValidationTestResult result)
                : base(result)
            {
            }


            protected override void Body()
            {

                while (true)
                {

                    Select(s => s.
                        When(() => true).
                            Accept(Put, (p1, p2, p3, p4) => { }).
                    Or.
                        When(() => true).
                            Accept(Get, (p1, p2, p3, p4) => true).
                    Or.
                        When(() => true).
                            Accept(FPut, (i, p1, p2, p3, p4) => { }).
                    Or.
                        When(() => true).
                            Accept(FGet, (i, p1, p2, p3, p4) => true).
                    Or.
                        When((double i) => true).
                            Accept(FPut, (i, p1, p2, p3, p4) => { }).
                    Or.
                        When((double i) => true).
                            Accept(FGet, (i, p1, p2, p3, p4) => true).
                    Or.
                        When(() => true).
                            Accept(FPut[0.0], (double i, int p1, int p2, int p3, int p4) => { }).
                    Or.
                        When(() => true).
                            Accept(FGet[0.0], (double i, int p1, int p2, int p3, int p4) => true).
                    Or.
                        Terminate
                    );

                }
                    
            }
            protected override void Exception(Exception ex)
            {
                Result.TestFailed();
                base.Exception(ex);
            }

        }
        
        
        [Test]
        public void SynchronousCall_StraightAccept()
        {
            StraightAccept0 task0 = null;
            StraightAccept1 task1 = null;
            StraightAccept2 task2 = null;
            StraightAccept3 task3 = null;
            StraightAccept4 task4 = null;
            IValidationTestResult result = Mocks.DynamicMock<IValidationTestResult>();

            Ada.Declare(() =>
            {
                task0 = new StraightAccept0(result);
                task1 = new StraightAccept1(result);
                task2 = new StraightAccept2(result);
                task3 = new StraightAccept3(result);
                task4 = new StraightAccept4(result);
                
                // Setup text expectations

                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task0));
                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task1));
                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task2));
                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task3));
                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task4));
                
                Mocks.ReplayAll();
            },
            Begin: () =>
            {
                // Start test execution
                
                task0.Put();
                task1.Put(1);
                task2.Put(1, 2);
                task3.Put(1, 2, 3);
                task4.Put(1, 2, 3, 4);
                
                task0.Get();
                task1.Get(1);
                task2.Get(1, 2);
                task3.Get(1, 2, 3);
                task4.Get(1, 2, 3, 4);
                
                task0.FPut[0.0]();
                task1.FPut[0.0](1);
                task2.FPut[0.0](1, 2);
                task3.FPut[0.0](1, 2, 3);
                task4.FPut[0.0](1, 2, 3, 4);
                
                task0.FGet[0.0]();
                task1.FGet[0.0](1);
                task2.FGet[0.0](1, 2);
                task3.FGet[0.0](1, 2, 3);
                task4.FGet[0.0](1, 2, 3, 4);
                
                task0.FPut[0.0]();
                task1.FPut[0.0](1);
                task2.FPut[0.0](1, 2);
                task3.FPut[0.0](1, 2, 3);
                task4.FPut[0.0](1, 2, 3, 4);
                
                task0.FGet[0.0]();
                task1.FGet[0.0](1);
                task2.FGet[0.0](1, 2);
                task3.FGet[0.0](1, 2, 3);
                task4.FGet[0.0](1, 2, 3, 4);
                
            });
        }


        [Test]
        public void SynchronousCall_SelectiveAccept()
        {
            SelectiveAccept0 task0 = null;
            SelectiveAccept1 task1 = null;
            SelectiveAccept2 task2 = null;
            SelectiveAccept3 task3 = null;
            SelectiveAccept4 task4 = null;
            IValidationTestResult result = Mocks.DynamicMock<IValidationTestResult>();

            Ada.Declare(() =>
            {
                task0 = new SelectiveAccept0(result);
                task1 = new SelectiveAccept1(result);
                task2 = new SelectiveAccept2(result);
                task3 = new SelectiveAccept3(result);
                task4 = new SelectiveAccept4(result);
                
                // Setup text expectations

                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task0));
                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task1));
                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task2));
                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task3));
                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task4));
                
                Mocks.ReplayAll();
            },
            Begin: () =>
            {
                // Start test execution

                task0.Put();
                task1.Put(1);
                task2.Put(1, 2);
                task3.Put(1, 2, 3);
                task4.Put(1, 2, 3, 4);
                
                task0.Get();
                task1.Get(1);
                task2.Get(1, 2);
                task3.Get(1, 2, 3);
                task4.Get(1, 2, 3, 4);
                
                task0.FPut[0.0]();
                task1.FPut[0.0](1);
                task2.FPut[0.0](1, 2);
                task3.FPut[0.0](1, 2, 3);
                task4.FPut[0.0](1, 2, 3, 4);
                
                task0.FGet[0.0]();
                task1.FGet[0.0](1);
                task2.FGet[0.0](1, 2);
                task3.FGet[0.0](1, 2, 3);
                task4.FGet[0.0](1, 2, 3, 4);
                
                task0.FPut[0.0]();
                task1.FPut[0.0](1);
                task2.FPut[0.0](1, 2);
                task3.FPut[0.0](1, 2, 3);
                task4.FPut[0.0](1, 2, 3, 4);
                
                task0.FGet[0.0]();
                task1.FGet[0.0](1);
                task2.FGet[0.0](1, 2);
                task3.FGet[0.0](1, 2, 3);
                task4.FGet[0.0](1, 2, 3, 4);
                
            });
        }


        [Test]
        public void DelayedCall_SelectiveAccept()
        {
            SelectiveAccept0 task0 = null;
            SelectiveAccept1 task1 = null;
            SelectiveAccept2 task2 = null;
            SelectiveAccept3 task3 = null;
            SelectiveAccept4 task4 = null;
            IValidationTestResult result = Mocks.DynamicMock<IValidationTestResult>();

            Ada.Declare(() =>
            {
                task0 = new SelectiveAccept0(result);
                task1 = new SelectiveAccept1(result);
                task2 = new SelectiveAccept2(result);
                task3 = new SelectiveAccept3(result);
                task4 = new SelectiveAccept4(result);
                
                // Setup text expectations

                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task0));
                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task1));
                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task2));
                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task3));
                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task4));
                
                Mocks.ReplayAll();
            },
            Begin: () =>
            {
                // Start test execution

                Ada.Select(s => s.
                    Call(task0.Put)().Then(() =>
                    {
                        ;
                    }).
                OrDelay(1.0).Then(() =>
                {
                    result.TestFailed();
                }));
                Ada.Select(s => s.
                    Call(task1.Put)(1).Then(() =>
                    {
                        ;
                    }).
                OrDelay(1.0).Then(() =>
                {
                    result.TestFailed();
                }));
                Ada.Select(s => s.
                    Call(task2.Put)(1, 2).Then(() =>
                    {
                        ;
                    }).
                OrDelay(1.0).Then(() =>
                {
                    result.TestFailed();
                }));
                Ada.Select(s => s.
                    Call(task3.Put)(1, 2, 3).Then(() =>
                    {
                        ;
                    }).
                OrDelay(1.0).Then(() =>
                {
                    result.TestFailed();
                }));
                Ada.Select(s => s.
                    Call(task4.Put)(1, 2, 3, 4).Then(() =>
                    {
                        ;
                    }).
                OrDelay(1.0).Then(() =>
                {
                    result.TestFailed();
                }));
                
                Ada.Select(s => s.
                    Call(task0.Get)().Then((res) =>
                    {
                        ;
                    }).
                OrDelay(1000).Then(() =>
                {
                    result.TestFailed();
                }));
                Ada.Select(s => s.
                    Call(task1.Get)(1).Then((res) =>
                    {
                        ;
                    }).
                OrDelay(1000).Then(() =>
                {
                    result.TestFailed();
                }));
                Ada.Select(s => s.
                    Call(task2.Get)(1, 2).Then((res) =>
                    {
                        ;
                    }).
                OrDelay(1000).Then(() =>
                {
                    result.TestFailed();
                }));
                Ada.Select(s => s.
                    Call(task3.Get)(1, 2, 3).Then((res) =>
                    {
                        ;
                    }).
                OrDelay(1000).Then(() =>
                {
                    result.TestFailed();
                }));
                Ada.Select(s => s.
                    Call(task4.Get)(1, 2, 3, 4).Then((res) =>
                    {
                        ;
                    }).
                OrDelay(1000).Then(() =>
                {
                    result.TestFailed();
                }));
                
                Ada.Select(s => s.
                    Call(task0.FPut[0.0])().Then(() =>
                    {
                        ;
                    }).
                OrDelay(new TimeSpan(0, 0, 1)).Then(() =>
                {
                    result.TestFailed();
                }));
                Ada.Select(s => s.
                    Call(task1.FPut[0.0])(1).Then(() =>
                    {
                        ;
                    }).
                OrDelay(new TimeSpan(0, 0, 1)).Then(() =>
                {
                    result.TestFailed();
                }));
                Ada.Select(s => s.
                    Call(task2.FPut[0.0])(1, 2).Then(() =>
                    {
                        ;
                    }).
                OrDelay(new TimeSpan(0, 0, 1)).Then(() =>
                {
                    result.TestFailed();
                }));
                Ada.Select(s => s.
                    Call(task3.FPut[0.0])(1, 2, 3).Then(() =>
                    {
                        ;
                    }).
                OrDelay(new TimeSpan(0, 0, 1)).Then(() =>
                {
                    result.TestFailed();
                }));
                Ada.Select(s => s.
                    Call(task4.FPut[0.0])(1, 2, 3, 4).Then(() =>
                    {
                        ;
                    }).
                OrDelay(new TimeSpan(0, 0, 1)).Then(() =>
                {
                    result.TestFailed();
                }));
                
                Ada.Select(s => s.
                    Call(task0.FGet[0.0])().Then((res) =>
                    {
                        ;
                    }).
                OrDelay(DateTime.Now.AddSeconds(1.0)).Then(() =>
                {
                    result.TestFailed();
                }));
                Ada.Select(s => s.
                    Call(task1.FGet[0.0])(1).Then((res) =>
                    {
                        ;
                    }).
                OrDelay(DateTime.Now.AddSeconds(1.0)).Then(() =>
                {
                    result.TestFailed();
                }));
                Ada.Select(s => s.
                    Call(task2.FGet[0.0])(1, 2).Then((res) =>
                    {
                        ;
                    }).
                OrDelay(DateTime.Now.AddSeconds(1.0)).Then(() =>
                {
                    result.TestFailed();
                }));
                Ada.Select(s => s.
                    Call(task3.FGet[0.0])(1, 2, 3).Then((res) =>
                    {
                        ;
                    }).
                OrDelay(DateTime.Now.AddSeconds(1.0)).Then(() =>
                {
                    result.TestFailed();
                }));
                Ada.Select(s => s.
                    Call(task4.FGet[0.0])(1, 2, 3, 4).Then((res) =>
                    {
                        ;
                    }).
                OrDelay(DateTime.Now.AddSeconds(1.0)).Then(() =>
                {
                    result.TestFailed();
                }));
                
            });
        }


        [Test]
        public void AbortableCall_SelectiveAccept()
        {
            SelectiveAccept0 task0 = null;
            SelectiveAccept1 task1 = null;
            SelectiveAccept2 task2 = null;
            SelectiveAccept3 task3 = null;
            SelectiveAccept4 task4 = null;
            IValidationTestResult result = Mocks.DynamicMock<IValidationTestResult>();

            Ada.Declare(() =>
            {
                task0 = new SelectiveAccept0(result);
                task1 = new SelectiveAccept1(result);
                task2 = new SelectiveAccept2(result);
                task3 = new SelectiveAccept3(result);
                task4 = new SelectiveAccept4(result);
                
                // Setup text expectations

                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task0));
                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task1));
                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task2));
                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task3));
                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task4));
                
                Mocks.ReplayAll();
            },
            Begin: () =>
            {
                // Start test execution

                Ada.Select(s => s.
                    Delay(1.0).
                ThenAbort(() =>
                {
                    task0.Put();
                }));
                Ada.Select(s => s.
                    Delay(1.0).
                ThenAbort(() =>
                {
                    task1.Put(1);
                }));
                Ada.Select(s => s.
                    Delay(1.0).
                ThenAbort(() =>
                {
                    task2.Put(1, 2);
                }));
                Ada.Select(s => s.
                    Delay(1.0).
                ThenAbort(() =>
                {
                    task3.Put(1, 2, 3);
                }));
                Ada.Select(s => s.
                    Delay(1.0).
                ThenAbort(() =>
                {
                    task4.Put(1, 2, 3, 4);
                }));
                
                Ada.Select(s => s.
                    Delay(1000).
                ThenAbort(() =>
                {
                    task0.Get();
                }));
                Ada.Select(s => s.
                    Delay(1000).
                ThenAbort(() =>
                {
                    task1.Get(1);
                }));
                Ada.Select(s => s.
                    Delay(1000).
                ThenAbort(() =>
                {
                    task2.Get(1, 2);
                }));
                Ada.Select(s => s.
                    Delay(1000).
                ThenAbort(() =>
                {
                    task3.Get(1, 2, 3);
                }));
                Ada.Select(s => s.
                    Delay(1000).
                ThenAbort(() =>
                {
                    task4.Get(1, 2, 3, 4);
                }));
                
                Ada.Select(s => s.
                    Delay(new TimeSpan(0, 0, 1)).
                ThenAbort(() =>
                {
                    task0.FPut[0.0]();
                }));
                Ada.Select(s => s.
                    Delay(new TimeSpan(0, 0, 1)).
                ThenAbort(() =>
                {
                    task1.FPut[0.0](1);
                }));
                Ada.Select(s => s.
                    Delay(new TimeSpan(0, 0, 1)).
                ThenAbort(() =>
                {
                    task2.FPut[0.0](1, 2);
                }));
                Ada.Select(s => s.
                    Delay(new TimeSpan(0, 0, 1)).
                ThenAbort(() =>
                {
                    task3.FPut[0.0](1, 2, 3);
                }));
                Ada.Select(s => s.
                    Delay(new TimeSpan(0, 0, 1)).
                ThenAbort(() =>
                {
                    task4.FPut[0.0](1, 2, 3, 4);
                }));
                
                Ada.Select(s => s.
                    Delay(DateTime.Now.AddSeconds(1.0)).
                ThenAbort(() =>
                {
                    task0.FGet[0.0]();
                }));
                Ada.Select(s => s.
                    Delay(DateTime.Now.AddSeconds(1.0)).
                ThenAbort(() =>
                {
                    task1.FGet[0.0](1);
                }));
                Ada.Select(s => s.
                    Delay(DateTime.Now.AddSeconds(1.0)).
                ThenAbort(() =>
                {
                    task2.FGet[0.0](1, 2);
                }));
                Ada.Select(s => s.
                    Delay(DateTime.Now.AddSeconds(1.0)).
                ThenAbort(() =>
                {
                    task3.FGet[0.0](1, 2, 3);
                }));
                Ada.Select(s => s.
                    Delay(DateTime.Now.AddSeconds(1.0)).
                ThenAbort(() =>
                {
                    task4.FGet[0.0](1, 2, 3, 4);
                }));
                
            });
        }


        [Test]
        public void AsynchronousCall_SelectiveAccept()
        {
            SelectiveAccept0 task0 = null;
            SelectiveAccept1 task1 = null;
            SelectiveAccept2 task2 = null;
            SelectiveAccept3 task3 = null;
            SelectiveAccept4 task4 = null;
            IValidationTestResult result = Mocks.DynamicMock<IValidationTestResult>();

            Ada.Declare(() =>
            {
                task0 = new SelectiveAccept0(result);
                task1 = new SelectiveAccept1(result);
                task2 = new SelectiveAccept2(result);
                task3 = new SelectiveAccept3(result);
                task4 = new SelectiveAccept4(result);
                
                // Setup text expectations

                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task0));
                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task1));
                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task2));
                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task3));
                Expect.Call(() => result.TaskFinished(null)).IgnoreArguments().Constraints(Is.Same(task4));
                
                Mocks.ReplayAll();
            },
            Begin: () =>
            {
                // Start test execution

                List<Future> futures = new List<Future>();
                Future aFuture;
                //Future<bool> fFuture;

                task0.Put.Async().Wait();
                task1.Put.Async(1).Wait();
                task2.Put.Async(1, 2).Wait();
                task3.Put.Async(1, 2, 3).Wait();
                task4.Put.Async(1, 2, 3, 4).Wait();
                
                task0.Get.Async().Result();
                task1.Get.Async(1).Result();
                task2.Get.Async(1, 2).Result();
                task3.Get.Async(1, 2, 3).Result();
                task4.Get.Async(1, 2, 3, 4).Result();
                
                task0.FPut[0.0].Async().Wait();
                task1.FPut[0.0].Async(1).Wait();
                task2.FPut[0.0].Async(1, 2).Wait();
                task3.FPut[0.0].Async(1, 2, 3).Wait();
                task4.FPut[0.0].Async(1, 2, 3, 4).Wait();
                
                task0.FGet[0.0].Async().Result();
                task1.FGet[0.0].Async(1).Result();
                task2.FGet[0.0].Async(1, 2).Result();
                task3.FGet[0.0].Async(1, 2, 3).Result();
                task4.FGet[0.0].Async(1, 2, 3, 4).Result();
                
                futures.Add(task0.Put.Async());
                futures.Add(task1.Put.Async(1));
                futures.Add(task2.Put.Async(1, 2));
                futures.Add(task3.Put.Async(1, 2, 3));
                futures.Add(task4.Put.Async(1, 2, 3, 4));
                
                futures.Add(task0.Get.Async());
                futures.Add(task1.Get.Async(1));
                futures.Add(task2.Get.Async(1, 2));
                futures.Add(task3.Get.Async(1, 2, 3));
                futures.Add(task4.Get.Async(1, 2, 3, 4));
                
                futures.Add(task0.FPut[0.0].Async());
                futures.Add(task1.FPut[0.0].Async(1));
                futures.Add(task2.FPut[0.0].Async(1, 2));
                futures.Add(task3.FPut[0.0].Async(1, 2, 3));
                futures.Add(task4.FPut[0.0].Async(1, 2, 3, 4));
                
                futures.Add(task0.FGet[0.0].Async());
                futures.Add(task1.FGet[0.0].Async(1));
                futures.Add(task2.FGet[0.0].Async(1, 2));
                futures.Add(task3.FGet[0.0].Async(1, 2, 3));
                futures.Add(task4.FGet[0.0].Async(1, 2, 3, 4));
                
                aFuture = Future.WaitAny(futures);
                futures.Remove(aFuture);

                Future.WaitAll(futures);
            });
        }

    }

}
